home *** CD-ROM | disk | FTP | other *** search
/ CD Actual 85 / CD Temático 40 Febrero 2004.iso / DOS / testdisk / src / hdaccess.c < prev    next >
Encoding:
C/C++ Source or Header  |  2004-01-09  |  33.5 KB  |  1,111 lines

  1. /*
  2.  
  3.     File: hdaccess.c
  4.  
  5.     Copyright (C) 1998-2004 Christophe GRENIER <grenier@cgsecurity.org>
  6.   
  7.     This software is free software; you can redistribute it and/or modify
  8.     it under the terms of the GNU General Public License as published by
  9.     the Free Software Foundation; either version 2 of the License, or
  10.     (at your option) any later version.
  11.   
  12.     This program is distributed in the hope that it will be useful,
  13.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.     GNU General Public License for more details.
  16.   
  17.     You should have received a copy of the GNU General Public License
  18.     along with this program; if not, write to the Free Software
  19.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20.  
  21.  */
  22. #include <stdio.h>
  23. #include <sys/stat.h>
  24. #include <unistd.h>    /* lseek, read, write, close */
  25. #include <string.h>
  26. #include <fcntl.h>     /* open */
  27. #include <errno.h>
  28. #ifdef DJGPP
  29. #include <stdlib.h>     /* atexit */
  30. #include <go32.h>       /* dosmemget/put */
  31. #include <dpmi.h>
  32. #include <bios.h>       /* bios_k* */
  33. #elif defined(LINUX)
  34. #include <sys/ioctl.h>
  35. #include <features.h>
  36. #include <linux/hdreg.h>
  37. #include <sys/mount.h>    /* BLKFLSBUF */
  38. #else
  39. #include <sys/ioctl.h>
  40. #include <sys/disklabel.h>
  41. #include <sys/disk.h>
  42. #endif
  43. #include "types.h"
  44. #include "common.h"
  45. #include "fnctdsk.h"
  46. #include "hdaccess.h"
  47. #include "readpart.h"
  48. #ifndef O_BINARY
  49. #define O_BINARY 0
  50. #endif
  51.  
  52. struct info_file
  53. {
  54.   int handle;
  55.   unsigned int offset;
  56.   char name[DISKNAME_MAX];
  57. };
  58.  
  59. static char *file_description(t_param_disk *disk_car);
  60. static int file_clean(t_param_disk *disk_car);
  61. static int file_read(t_param_disk *disk_car, const unsigned int nbr_sector, void *nom_buffer, const dword pos);
  62. static int file_write(t_param_disk *disk_car, const unsigned int nbr_sector, const void *nom_buffer, const dword pos);
  63. static int file_nowrite(t_param_disk *disk_car, const unsigned int nbr_sector, const void *nom_buffer, const dword pos);
  64.  
  65. #ifdef DJGPP
  66. #define HD_RW_BUF_SIZ 0x10
  67. #define HDPARM_BUF_SIZ 0x1A
  68. #define MAX_IO_NBR 3
  69. #define MAX_HD_ERR 100
  70. #define PARA_CMD         8
  71. static int hd_super(int cmd, t_param_disk *disk_car, dword hd_offset, int nsects, void *buffer);
  72. static t_param_disk *hd_identify(const int debug, const unsigned int disk);
  73. static int hd_identify_enh_bios(t_param_disk *param_disk,const int debug);
  74. static int check_enh_bios(const unsigned int disk, const int debug);
  75. static int hd_report_error(t_param_disk *disk_car, const dword hd_offset, const unsigned int nbr_sector, const int rc);
  76. static char *disk_description(t_param_disk *disk_car);
  77. static int disk_read(t_param_disk *disk_car, const unsigned int nbr_sector, void *nom_buffer, const dword hd_offset);
  78. static int disk_write(t_param_disk *disk_car, const unsigned int nbr_sector, const void *nom_buffer, const dword hd_offset);
  79. struct info_disk
  80. {
  81.   unsigned int disk;
  82.   t_CHS CHSR;    /* CHS low level */
  83.   int mode;
  84.   unsigned int nbr_err;
  85.   int bad_geometry;
  86. };
  87.  
  88. static int dos_segment = 0;
  89. static int dos_selector = 0;
  90.  
  91. void free_dos_buffer(void)
  92. {
  93.   __dpmi_free_dos_memory(dos_selector);
  94.   dos_segment = dos_selector = 0;
  95. }
  96.  
  97. int alloc_dos_buffer(void)
  98. {
  99.   if (dos_segment)
  100.     return 0;
  101.   if ((dos_segment = __dpmi_allocate_dos_memory(18*SECTOR_SIZE/16, &dos_selector))== -1)
  102.   {
  103.     dos_segment = 0;
  104.     return 1;
  105.   }
  106.   atexit(free_dos_buffer);
  107.   return 0;
  108. }
  109.  
  110. static int hd_super(int cmd, t_param_disk *disk_car, dword hd_offset, int nsects, void *buffer)
  111.   __dpmi_regs r;
  112.   unsigned char buf[HD_RW_BUF_SIZ];
  113.   int dos_segment2, dos_selector2, xfer2=nsects*SECTOR_SIZE;
  114.   struct info_disk*data=disk_car->data;
  115.  
  116.   if((data->mode==0)||(cmd==0))
  117.   { /* Limite CHS = 1023,255,63 = 8,064Mo ~= 7.8 Go */
  118.     int head, track, sector;
  119.     sector=(hd_offset%data->CHSR.sector)+1;
  120.     hd_offset/=data->CHSR.sector;
  121.     head=hd_offset%(data->CHSR.head+1);
  122.     track=hd_offset/(data->CHSR.head+1);
  123.     if(track<1024)
  124.       return biosdisk(cmd, data->disk, head, track, sector, nsects, buffer);
  125.     return 1;
  126.   }
  127.   if(dos_segment==0)
  128.     if(alloc_dos_buffer())
  129.       return 1;
  130.   if ( (dos_segment2=__dpmi_allocate_dos_memory((xfer2 + 15) >> 4, &dos_selector2)) == -1 )
  131.     return 1;
  132.   *(word*)&buf[0]=HD_RW_BUF_SIZ;
  133.   *(word*)&buf[2]=nsects;
  134.   *(dword*)&buf[0x4]=dos_segment2<<16;
  135.   *(dword*)&buf[0x8]=hd_offset;
  136.   *(dword*)&buf[0xC]=0;
  137.  
  138.   r.x.ds = dos_segment;
  139.   r.x.si = 0;
  140.   r.h.dl = data->disk;
  141.   switch(cmd)
  142.   {
  143.     case 2:
  144.       r.h.ah = 0x42;
  145.       break;
  146.     case 3:
  147.       r.x.ax = 0x4300;
  148.       dosmemput(buffer,xfer2,dos_segment2<<4);
  149.       break;
  150.     case 0x0C:
  151.       r.h.ah = 0x47;
  152.       break;
  153.   }
  154.   dosmemput(&buf, HD_RW_BUF_SIZ, dos_segment<<4);
  155.   __dpmi_int(0x13, &r);
  156.   if(cmd==2)
  157.     dosmemget(dos_segment2<<4, xfer2, buffer);
  158.   __dpmi_free_dos_memory(dos_selector2);
  159. #ifdef DEBUG
  160.   if(r.h.ah)
  161.   {
  162.     wdoprintf(stdscr," %lu err %02X %04X\n",*(dword*)&buf[0x8], r.h.ah,r.x.flags);
  163.   }
  164. #endif
  165.   return r.h.ah;
  166. }
  167.  
  168. static int check_enh_bios(const unsigned int disk, const int debug)
  169. {
  170.   __dpmi_regs r;
  171.   r.h.ah = 0x41;
  172.   r.x.bx = 0x55AA;
  173.   r.h.dl = disk;
  174.   __dpmi_int(0x13, &r);
  175.   if(r.x.bx != 0xAA55)  /* INT 13 Extensions not installed */
  176.   {
  177.     if(debug)
  178.       ecrit_rapport("Disk %02X - INT 13 Extensions not installed\n",disk);
  179.     return 0;
  180.   }
  181.   if(debug)
  182.   {
  183.     ecrit_rapport("Disk %02X ",disk);
  184.     switch(r.h.ah)
  185.     {
  186.       case 0x01:
  187.         ecrit_rapport("Enhanced BIOS 1.x");
  188.         break;
  189.       case 0x20:
  190.         ecrit_rapport("Enhanced BIOS 2.0 / EDD-1.0");
  191.         break;
  192.       case 0x21:
  193.         ecrit_rapport("Enhanced BIOS 2.1 / EDD-1.1");
  194.         break;
  195.       case 0x30:
  196.         ecrit_rapport("Enhanced BIOS EDD-3.0");
  197.         break;
  198.       default:
  199.         ecrit_rapport("Enhanced BIOS unknown %02X",r.h.ah);
  200.         break;
  201.     }
  202.     if((r.x.cx & 1)!=0)
  203.       ecrit_rapport(" - R/W/I");
  204.     if((r.x.cx & 4)!=0)
  205.       ecrit_rapport(" - Identify");
  206.     ecrit_rapport("\n");
  207.   }
  208.   return ((r.x.cx&1)!=0);
  209. }
  210.  
  211. static int hd_identify_enh_bios(t_param_disk *disk_car,const int debug)
  212. {
  213.   int compute_LBA=0;
  214.   __dpmi_regs r;
  215.   unsigned char buf[0x200];    /* Don't change it! */
  216.   struct info_disk*data=disk_car->data;
  217.   buf[0]=HDPARM_BUF_SIZ;
  218.   buf[1]=0;
  219.   if(dos_segment==0)
  220.     if(alloc_dos_buffer())
  221.       return 1;
  222.   r.h.ah = 0x48;
  223.   r.x.ds = dos_segment;
  224.   r.x.si = 0;
  225.   r.h.dl = data->disk;
  226.   dosmemput(&buf, HDPARM_BUF_SIZ, dos_segment<<4);
  227.   __dpmi_int(0x13, &r);
  228.   dosmemget(dos_segment<<4, HDPARM_BUF_SIZ, &buf);
  229.   if(r.h.ah)
  230.     return 1;
  231.   disk_car->CHS.cylinder=*(word*)&buf[0x04];
  232.   disk_car->CHS.head=*(word*)&buf[0x08];
  233.   disk_car->CHS.sector=*(word*)&buf[0x0C];
  234.   disk_car->size=(*(dword*)&buf[0x10]);
  235.   if(disk_car->size==0)
  236.   {
  237.     disk_car->CHS.cylinder--;
  238.     disk_car->CHS.head--;
  239.     compute_LBA=1;
  240.     disk_car->size=(disk_car->CHS.cylinder+1)*(disk_car->CHS.head+1)*disk_car->CHS.sector;
  241.     if(debug)
  242.       ecrit_rapport("Computes LBA from CHS\n");
  243.   }
  244.   else
  245.   {
  246.     if(disk_car->CHS.cylinder>0 && disk_car->CHS.head>0 && disk_car->CHS.sector>0)
  247.     {
  248.       disk_car->CHS.cylinder--;
  249.       disk_car->CHS.head--;
  250.       /* Some bios are buggy */
  251.       if(disk_car->size>(disk_car->CHS.cylinder+2)*(disk_car->CHS.head+1)*disk_car->CHS.sector)
  252.       {
  253.     disk_car->CHS.cylinder=(disk_car->size/(disk_car->CHS.head+1))/disk_car->CHS.sector-1;
  254.     if(debug)
  255.       ecrit_rapport("Computes C from number of sectors\n");
  256.       }
  257.     }
  258.     else
  259.     {
  260.       if(debug)
  261.     ecrit_rapport("Computes CHS from number of sectors\n");
  262.       disk_car->CHS.head=255-1;
  263.       disk_car->CHS.sector=63;
  264.       disk_car->CHS.cylinder=(disk_car->size/(disk_car->CHS.head+1))/disk_car->CHS.sector-1;
  265.     }
  266.   }
  267.   if(disk_car->CHS.sector==0)
  268.   {
  269.     data->bad_geometry=1;
  270.     disk_car->CHS.sector=1;
  271.     ecrit_rapport("Incorrect number of sector\n");
  272.   }
  273.   if(disk_car->CHS.sector>63)
  274.   {
  275.     data->bad_geometry=1;
  276.     ecrit_rapport("Incorrect number of sector\n");
  277.   }
  278.   if(disk_car->CHS.head>255-1)
  279.   {
  280.     data->bad_geometry=1;
  281.     ecrit_rapport("Incorrect number of head\n");
  282.   }
  283.   if(debug || data->bad_geometry)
  284.     ecrit_rapport("LBA %lu, computed %u (CHS=%u,%u,%u)\n",disk_car->size, (disk_car->CHS.cylinder+1)*(disk_car->CHS.head+1)*disk_car->CHS.sector,disk_car->CHS.cylinder,disk_car->CHS.head,disk_car->CHS.sector);
  285.   if(compute_LBA)
  286.     disk_car->size=(disk_car->CHS.cylinder+1)*(disk_car->CHS.head+1)*disk_car->CHS.sector;
  287.   else
  288.   {
  289.     if(disk_car->size < (disk_car->CHS.cylinder+1)*(disk_car->CHS.head+1)*disk_car->CHS.sector)
  290.     {
  291.       ecrit_rapport("Computes LBA from CHS, previous value may be false.\n");
  292.       disk_car->size=(disk_car->CHS.cylinder+1)*(disk_car->CHS.head+1)*disk_car->CHS.sector;
  293.     }
  294.   }
  295.   data->CHSR.cylinder=disk_car->CHS.cylinder;
  296.   data->CHSR.head=disk_car->CHS.head;
  297.   data->CHSR.sector=disk_car->CHS.sector;
  298.   if(debug)
  299.   {
  300.     ecrit_rapport("hd_identify_enh_bios\n");
  301.     ecrit_rapport("%s",disk_description(disk_car));
  302.     ecrit_rapport("LBA size=%lu\n",disk_car->size);
  303.   }
  304.   return 0;
  305. }
  306.  
  307. static t_param_disk *hd_identify(const int debug, const unsigned int disk)
  308. {
  309.   unsigned char buf[0x200];
  310.   memset(buf,0,sizeof(buf));
  311.   /* standard BIOS access */
  312.   if(biosdisk(PARA_CMD,disk,0,0,1,1,buf))
  313.     return NULL;
  314.   if(debug>1)
  315.     ecrit_rapport("Disk %02X %u max %02X\n",disk,buf[2],(0x80+buf[2]-1));
  316.   if(disk>(unsigned int)(0x80+buf[2]-1))
  317.     return NULL;
  318.   {
  319.     struct info_disk*data=(struct info_disk*)MALLOC(sizeof(*data));
  320.     t_param_disk *disk_car=(t_param_disk *)MALLOC(sizeof(*disk_car));
  321.     data->disk=disk;
  322.     data->bad_geometry=0;
  323.     data->mode=0;
  324.     data->nbr_err=0;
  325.     disk_car->halt_on_errors=0;
  326.     disk_car->write_used=0;
  327.     disk_car->description=disk_description;
  328.     disk_car->read=disk_read;
  329.     disk_car->write=disk_write;
  330.     disk_car->clean=file_clean;
  331.     disk_car->data=data;
  332.     disk_car->CHS.cylinder=((buf[0] & 0x0C0)<<2)|buf[1];
  333.     disk_car->CHS.head=buf[3];
  334.     disk_car->CHS.sector=buf[0] & 0x3F;
  335.     if(disk_car->CHS.head>=255)
  336.     { /* Problem found by G Rowe */
  337.       ecrit_rapport("BIOS reports an invalid heads number\n");
  338.       data->bad_geometry=1;
  339.       disk_car->CHS.head=254;
  340.     }
  341.     if(disk_car->CHS.sector==0)
  342.     { /* Problem found by Brian Barrett */
  343.       ecrit_rapport("BIOS reports an invalid number of sector per head\n");
  344.       data->bad_geometry=1;
  345.       disk_car->CHS.sector=1;
  346.     }
  347.     disk_car->size=(disk_car->CHS.cylinder+1)*(disk_car->CHS.head+1)*disk_car->CHS.sector;
  348.     data->CHSR.cylinder=disk_car->CHS.cylinder;
  349.     data->CHSR.head=disk_car->CHS.head;
  350.     data->CHSR.sector=disk_car->CHS.sector;
  351.     if(debug)
  352.       ecrit_rapport("%s",disk_description(disk_car));
  353.     if(check_enh_bios(disk,debug))
  354.     {
  355.       /* enhanced BIOS access */
  356.       t_param_disk *param_disk_enh=(t_param_disk*)MALLOC(sizeof(*param_disk_enh));
  357.       param_disk_enh->halt_on_errors=0;
  358.       param_disk_enh->write_used=0;
  359.       param_disk_enh->data=data;
  360.       data->mode=1;
  361.       if(!hd_identify_enh_bios(param_disk_enh,debug))
  362.       {
  363.     /* standard geometry H,S, compute C from LBA */
  364.     disk_car->size=param_disk_enh->size;
  365.     disk_car->CHS.cylinder=(disk_car->size/(disk_car->CHS.head+1))/disk_car->CHS.sector-1;
  366.       }
  367.       else
  368.     data->mode=0;
  369.       FREE(param_disk_enh);
  370.     }
  371.     return disk_car;
  372.   }
  373. }
  374.  
  375. static char *disk_description(t_param_disk *disk_car)
  376. {
  377.   struct info_disk*data=disk_car->data;
  378.   sprintf(disk_car->description_txt, "Disk %2x - CHS %u %u %u - %u MB %s\n",
  379.       data->disk, disk_car->CHS.cylinder+1, disk_car->CHS.head+1, disk_car->CHS.sector,(disk_car->CHS.cylinder+1)*(disk_car->CHS.head+1)*disk_car->CHS.sector/2/1024,data->bad_geometry?" (Buggy BIOS)":"");
  380.   return disk_car->description_txt;
  381. }
  382.  
  383. static int disk_read(t_param_disk *disk_car,const unsigned int nbr_sector, void *nom_buffer, const dword hd_offset)
  384. {
  385.   struct info_disk*data=disk_car->data;
  386.   /* CHS=(0,1,1) */
  387.   if(hd_offset==disk_car->CHS.sector)
  388.   {
  389.     data->nbr_err=0;
  390.   }
  391.   if((data->nbr_err>MAX_HD_ERR)&&disk_car->halt_on_errors)
  392.   {
  393.     if(data->nbr_err==(MAX_HD_ERR+1))
  394.     {
  395.       ecrit_rapport("\ndata->nbr_err>MAX_HD_ERR !!!\n");
  396.       data->nbr_err++;
  397.     }
  398.     return 1;
  399.   }
  400.   if((data->CHSR.cylinder==0) || (hd_offset+nbr_sector-1<=disk_car->size))
  401.   {
  402.     int rc=0;
  403.     unsigned int offset=0;
  404.     unsigned int read_size;
  405.     for(offset=0;(rc==0) && (offset<nbr_sector);offset+=read_size)
  406.     {
  407.       int i;
  408.       read_size=nbr_sector-offset>16?16:nbr_sector-offset;
  409.       rc=4; /* sector not found/read error */
  410.       for(i=0;(rc!=0) && (rc!=1) && (i<MAX_IO_NBR);i++)
  411.       {
  412.     rc=hd_super(2, disk_car, hd_offset+offset, read_size, (char*)nom_buffer+offset*SECTOR_SIZE);
  413.     if(rc!=0)
  414.     {
  415.       hd_super(0, disk_car, 0, 1, NULL);
  416.     }
  417.       }
  418.     }
  419.     if(rc!=0)
  420.     {
  421.       ecrit_rapport("disk_read");
  422.       hd_report_error(disk_car,hd_offset,nbr_sector,rc);
  423.     }
  424.     return rc;
  425.   }
  426.   return 1;
  427. }
  428.  
  429. static int disk_write(t_param_disk *disk_car,const unsigned int nbr_sector, const void *nom_buffer, const dword hd_offset)
  430. {
  431.   struct info_disk*data=disk_car->data;
  432.   disk_car->write_used=1;
  433.   if((data->nbr_err>MAX_HD_ERR)&&disk_car->halt_on_errors)
  434.   {
  435.     if(data->nbr_err==(MAX_HD_ERR+1))
  436.     {
  437.       ecrit_rapport("\ndata->nbr_err>MAX_HD_ERR !!!\n");
  438.       data->nbr_err++;
  439.     }
  440.     return 1;
  441.   }
  442.   {
  443.     int i,rc=4; /* sector not found/read error */
  444.     for(i=0;(rc==4)&&(i<MAX_IO_NBR);i++)
  445.     {
  446.       rc=hd_super(3, disk_car, hd_offset, nbr_sector, nom_buffer);
  447.     }
  448.     if(rc)
  449.     {
  450.       ecrit_rapport("disk_write");
  451.       hd_report_error(disk_car,hd_offset,nbr_sector,rc);
  452.     }
  453.     return rc;
  454.   }
  455. }
  456.  
  457. static int hd_report_error(t_param_disk *disk_car, const dword hd_offset, const unsigned int nbr_sector, const int rc)
  458. {
  459.   struct info_disk*data=disk_car->data;
  460.   data->nbr_err++;
  461.   ecrit_rapport(" lba=%lu(%u/%u/%u) nbr_sector=%u, rc=%d\n",hd_offset,
  462.       LBA2cylinder(disk_car,hd_offset),LBA2head(disk_car,hd_offset),LBA2sector(disk_car,hd_offset),
  463.       nbr_sector,rc);
  464.   switch(rc)
  465.   {
  466.     case 0x00: ecrit_rapport("successful completion"); break;
  467.     case 0x01: ecrit_rapport("invalid function in AH or invalid parameter"); break;
  468.     case 0x02: ecrit_rapport("address mark not found"); break;
  469.     case 0x03: ecrit_rapport("disk write-protected"); break;
  470.     case 0x04: ecrit_rapport("sector not found/read error"); break;
  471.     case 0x05: ecrit_rapport("reset failed (hard disk)"); break;
  472.     case 0x06: ecrit_rapport("disk changed (floppy)"); break;
  473.     case 0x07: ecrit_rapport("drive parameter activity failed (hard disk)"); break;
  474.     case 0x08: ecrit_rapport("DMA overrun"); break;
  475.     case 0x09: ecrit_rapport("data boundary error (attempted DMA across 64K boundary or >80h sectors)"); break;
  476.     case 0x0A: ecrit_rapport("bad sector detected (hard disk)"); break;
  477.     case 0x0B: ecrit_rapport("bad track detected (hard disk)"); break;
  478.     case 0x0C: ecrit_rapport("unsupported track or invalid media"); break;
  479.     case 0x0D: ecrit_rapport("invalid number of sectors on format (PS/2 hard disk)"); break;
  480.     case 0x0E: ecrit_rapport("control data address mark detected (hard disk)"); break;
  481.     case 0x0F: ecrit_rapport("DMA arbitration level out of range (hard disk)"); break;
  482.     case 0x10: ecrit_rapport("uncorrectable CRC or ECC error on read"); break;
  483.     case 0x11: ecrit_rapport("data ECC corrected (hard disk)"); break;
  484.     case 0x20: ecrit_rapport("controller failure"); break;
  485.     case 0x31: ecrit_rapport("no media in drive (IBM/MS INT 13 extensions)"); break;
  486.     case 0x32: ecrit_rapport("incorrect drive type stored in CMOS (Compaq)"); break;
  487.     case 0x40: ecrit_rapport("seek failed"); break;
  488.     case 0x80: ecrit_rapport("timeout (not ready)"); break;
  489.     case 0xAA: ecrit_rapport("drive not ready (hard disk)"); break;
  490.     case 0xB0: ecrit_rapport("volume not locked in drive (INT 13 extensions)"); break;
  491.     case 0xB1: ecrit_rapport("volume locked in drive (INT 13 extensions)"); break;
  492.     case 0xB2: ecrit_rapport("volume not removable (INT 13 extensions)"); break;
  493.     case 0xB3: ecrit_rapport("volume in use (INT 13 extensions)"); break;
  494.     case 0xB4: ecrit_rapport("lock count exceeded (INT 13 extensions)"); break;
  495.     case 0xB5: ecrit_rapport("valid eject request failed (INT 13 extensions)"); break;
  496.     case 0xB6: ecrit_rapport("volume present but read protected (INT 13 extensions)"); break;
  497.     case 0xBB: ecrit_rapport("undefined error (hard disk)"); break;
  498.     case 0xCC: ecrit_rapport("write fault (hard disk)"); break;
  499.     case 0xE0: ecrit_rapport("status register error (hard disk)"); break;
  500.     case 0xFF: ecrit_rapport("sense operation failed (hard disk)"); break;
  501.   }
  502.   ecrit_rapport("\n");
  503.   return 0;
  504. }
  505.  
  506. t_list_disk *hd_parse(t_list_disk *list_disk,const int debug)
  507. {
  508.   int i;
  509.   int ind_stop=0;
  510.   for(i=0x80;(i<0x88)&&!ind_stop;i++)
  511.   {
  512.     t_param_disk *disk_car=hd_identify(debug,i);
  513.     if(disk_car)
  514.       list_disk=insert_new_disk(list_disk,disk_car);
  515.     else
  516.       ind_stop=1;
  517.   }
  518.   /* hdimage */
  519.   {
  520.     t_param_disk *disk_car=file_test_availability( "hdimage",debug);
  521.     if(disk_car)
  522.       list_disk=insert_new_disk(list_disk,disk_car);
  523.   }
  524.   return list_disk;
  525. }
  526. #elif defined(LINUX)
  527. static t_param_disk *disk_get_geometry(const int hd_h, const char *device, const int debug);
  528.  
  529. static t_param_disk *disk_get_geometry(const int hd_h, const char *device, const int debug)
  530. {
  531.   t_param_disk *disk_car=NULL;
  532.   /* Little trick from Linux fdisk */
  533.   /* Blocks are visible in more than one way:
  534.      e.g. as block on /dev/hda and as block on /dev/hda3
  535.      By a bug in the Linux buffer cache, we will see the old
  536.      contents of /dev/hda when the change was made to /dev/hda3.
  537.      In order to avoid this, discard all blocks on /dev/hda. */
  538.   ioctl(hd_h, BLKFLSBUF);    /* ignore errors */
  539.   /* e.g. Permission Denied */
  540. #ifdef HDIO_GETGEO_BIG
  541.   {
  542.     struct hd_big_geometry geometry_big;
  543.     if (ioctl(hd_h, HDIO_GETGEO_BIG, &geometry_big)==0)
  544.     { /* I can get the geometry */
  545.       if(debug>1)
  546.       {
  547.     ecrit_rapport("disk_get_geometry %s HDIO_GETGEO_BIG Ok\n",device);
  548.       }
  549.       disk_car=(t_param_disk *)MALLOC(sizeof(*disk_car));
  550.       disk_car->CHS.cylinder= geometry_big.cylinders-1;
  551.       disk_car->CHS.head=geometry_big.heads-1;
  552.       disk_car->CHS.sector= geometry_big.sectors;
  553.     }
  554.     else
  555.     {
  556.       if(debug>1)
  557.       {
  558.     ecrit_rapport("disk_get_geometry %s: HDIO_GETGEO_BIG failed\n",device);
  559.       }
  560.     }
  561.   }
  562. #endif
  563.   if (disk_car==NULL)
  564.   {
  565.     struct hd_geometry geometry;
  566.     if(ioctl(hd_h, HDIO_GETGEO, &geometry)==0)
  567.     { /* I can get the geometry */
  568.       if(debug>1)
  569.       {
  570.     ecrit_rapport("disk_get_geometry %s HDIO_GETGEO Ok\n",device);
  571.       }
  572.       disk_car=(t_param_disk *)MALLOC(sizeof(*disk_car));
  573.       disk_car->CHS.cylinder= geometry.cylinders-1;
  574.       disk_car->CHS.head=geometry.heads-1;
  575.       disk_car->CHS.sector= geometry.sectors;
  576.     }
  577.   }
  578.   return disk_car;
  579. }
  580.  
  581. t_list_disk *hd_parse(t_list_disk *list_disk,const int debug)
  582. {
  583.   int i,j;
  584.   char device_ide[]="/dev/hda";
  585.   char device_scsi[]="/dev/sda";
  586.   char device_ida[]="/dev/ida/c0d0";
  587.   char device_cciss[]="/dev/cciss/c0d0";
  588.   char device_rd[]="/dev/rd/c0d0";
  589.   char device_rd_ide[]="/dev/ataraid/d0";
  590.   char device_p_ide[]="/dev/pda";
  591.   char device_i2o_hd[]="/dev/i2o/hda";
  592.   /* Disk IDE */
  593.   for(i=0;i<8;i++)
  594.   {
  595.     device_ide[strlen(device_ide)-1]='a'+i;
  596.     list_disk=insert_new_disk(list_disk,file_test_availability(device_ide,debug));
  597.   }
  598.   /* Disk SCSI */
  599.   for(i=0;i<26;i++)
  600.   {
  601.     device_scsi[strlen(device_scsi)-1]='a'+i;
  602.     list_disk=insert_new_disk(list_disk,file_test_availability(device_scsi,debug));
  603.   }
  604.   /* Device RAID Compaq */
  605.   for(j=0;j<8;j++)
  606.   {
  607.     device_ida[strlen(device_ida)-3]='0'+j;
  608.     for(i=0;i<8;i++)
  609.     {
  610.       device_ida[strlen(device_ida)-1]='0'+i;
  611.       list_disk=insert_new_disk(list_disk,file_test_availability(device_ida,debug));
  612.     }
  613.   }
  614.   for(i=0;i<8;i++)
  615.   {
  616.     device_cciss[strlen(device_cciss)-1]='0'+i;
  617.     list_disk=insert_new_disk(list_disk,file_test_availability(device_cciss,debug));
  618.   }
  619.   /* Device RAID */
  620.   for(i=0;i<10;i++)
  621.   {
  622.     device_rd[strlen(device_rd)-1]='0'+i;
  623.     list_disk=insert_new_disk(list_disk,file_test_availability(device_rd,debug));
  624.   }
  625.   /* Device RAID IDE */
  626.   for(i=0;i<15;i++)
  627.   {
  628.     device_rd_ide[strlen(device_rd_ide)-1]='0'+i;
  629.     list_disk=insert_new_disk(list_disk,file_test_availability(device_rd_ide,debug));
  630.   }
  631.   /* Parallel port IDE disk */
  632.   for(i=0;i<4;i++)
  633.   {
  634.     device_p_ide[strlen(device_p_ide)-1]='a'+i;
  635.     list_disk=insert_new_disk(list_disk,file_test_availability(device_p_ide,debug));
  636.   }
  637.   /* I2O hard disk */
  638.   for(i=0;i<26;i++)
  639.   {
  640.     device_i2o_hd[strlen(device_i2o_hd)-1]='a'+i;
  641.     list_disk=insert_new_disk(list_disk,file_test_availability(device_i2o_hd,debug));
  642.   }
  643. /* hdimage */
  644.   list_disk=insert_new_disk(list_disk,file_test_availability("hdimage",debug));
  645. #ifdef TEST
  646.   {
  647.     t_list_disk *disk;
  648.     for(disk=list_disk;disk;disk=disk->next)
  649.     {
  650.       disk->disk=new_diskcache(disk->disk);
  651.     }
  652.   }
  653. #endif
  654.   return list_disk;
  655. }
  656. #else
  657. static t_param_disk *disk_get_geometry(const int hd_h, const char *device, const int debug);
  658.  
  659. static t_param_disk *disk_get_geometry(const int hd_h, const char *device, const int debug)
  660. {
  661.   t_param_disk *disk_car=NULL;
  662.   struct disklabel geometry;
  663.   if (ioctl(hd_h, DIOCGDINFO, &geometry)==0)
  664.   { /* I can get the geometry */
  665.     if(debug>1)
  666.     {
  667.       ecrit_rapport("disk_get_geometry %s: Ok\n",device);
  668.     }
  669.     disk_car=(t_param_disk *)MALLOC(sizeof(*disk_car));
  670.     disk_car->CHS.cylinder=geometry.d_ncylinders-1;
  671.     disk_car->CHS.head=geometry.d_ntracks-1;
  672.     disk_car->CHS.sector=geometry.d_nsectors;
  673.   }
  674.   else
  675.   {
  676.     int error;
  677.     u_int u,sectors,heads,cyls;
  678.     off_t o;
  679.     if(debug>1)
  680.     {
  681.       ecrit_rapport("disk_get_geometry %s: DIOCGDINFO failed %s\n",device,strerror(errno));
  682.     }
  683.     error = ioctl(hd_h, DIOCGFWSECTORS, &u);
  684.     if(error==0 && u>0)
  685.     {
  686.       sectors=u;
  687.     }
  688.     else
  689.     {
  690.       sectors=63;
  691.       if(debug>1)
  692.       {
  693.     ecrit_rapport("disk_get_geometry %s: DIOCGFWSECTORS failed %s\n",device,strerror(errno));
  694.       }
  695.     }
  696.     error = ioctl(hd_h, DIOCGFWHEADS, &u);
  697.     if(error==0 && u>0)
  698.     {
  699.       heads=u;
  700.     }
  701.     else
  702.     {
  703.       heads=255;
  704.       if(debug>1)
  705.       {
  706.     ecrit_rapport("disk_get_geometry %s: DIOCGFWHEADS failed %s\n",device,strerror(errno));
  707.       }
  708.     }
  709.     error = ioctl(hd_h, DIOCGMEDIASIZE, &o);
  710.     if(error==0)
  711.     {
  712.       cyls = o / (512 * heads * sectors);
  713.       disk_car=(t_param_disk *)MALLOC(sizeof(*disk_car));
  714.       disk_car->CHS.cylinder=cyls-1;
  715.       disk_car->CHS.head=heads-1;
  716.       disk_car->CHS.sector=sectors;
  717.     }
  718.     else
  719.     {
  720.       if(debug>1)
  721.       {
  722.     ecrit_rapport("disk_get_geometry %s: DIOCGMEDIASIZE failed %s\n",device,strerror(errno));
  723.       }
  724.     }
  725.   }
  726.   return disk_car;
  727. }
  728.  
  729. t_list_disk *hd_parse(t_list_disk *list_disk,const int debug)
  730. {
  731.   /* Need to check http://mattriffle.com/mirrors/freebsd/doc/en_US.ISO8859-1/books/handbook/disks-naming.html#DISK-NAMING-PHYSICAL-TABLE */
  732.   int i;
  733.   char device_ide[]= "/dev/rwd0";    /* raw winchester disk */
  734.   char device_ide2[]="/dev/rad0";
  735.   char device_scsi[]="/dev/rda0";    /* raw scsci disk */
  736.   char device_optdisk[]="/dev/rod0";
  737.   char device_ide_hd[]="/dev/ad0";
  738.   char device_scsi_hd[]="/dev/da0";
  739. /* wd da */
  740.   /* Disk IDE */
  741.   for(i=0;i<8;i++)
  742.   {
  743.     device_ide[strlen(device_ide)-1]='0'+i;
  744.     list_disk=insert_new_disk(list_disk,file_test_availability(device_ide,debug));
  745.   }
  746.   for(i=0;i<8;i++)
  747.   {
  748.     device_ide2[strlen(device_ide2)-1]='0'+i;
  749.     list_disk=insert_new_disk(list_disk,file_test_availability(device_ide2,debug));
  750.   }
  751.   for(i=0;i<8;i++)
  752.   {
  753.     device_ide_hd[strlen(device_ide_hd)-1]='0'+i;
  754.     list_disk=insert_new_disk(list_disk,file_test_availability(device_ide_hd,debug));
  755.   }
  756.   /* Disk SCSI */
  757.   for(i=0;i<8;i++)
  758.   {
  759.     device_scsi[strlen(device_scsi)-1]='0'+i;
  760.     list_disk=insert_new_disk(list_disk,file_test_availability(device_scsi,debug));
  761.   }
  762.   for(i=0;i<8;i++)
  763.   {
  764.     device_scsi_hd[strlen(device_scsi_hd)-1]='0'+i;
  765.     list_disk=insert_new_disk(list_disk,file_test_availability(device_scsi_hd,debug));
  766.   }
  767.   /* optical disks */
  768.   for(i=0;i<8;i++)
  769.   {
  770.     device_optdisk[strlen(device_scsi)-1]='a'+i;
  771.     list_disk=insert_new_disk(list_disk,file_test_availability(device_optdisk,debug));
  772.   } 
  773.   /* */
  774.  
  775.   /* hdimage */
  776.   list_disk=insert_new_disk(list_disk,file_test_availability("hdimage",debug));
  777.   return list_disk;
  778. }
  779. #endif
  780.  
  781. static char *file_description(t_param_disk *disk_car)
  782. {
  783.   struct info_file *data=disk_car->data;
  784.   snprintf(disk_car->description_txt, sizeof(disk_car->description_txt),"Disk %s - CHS %u %u %u - %u MB\n",
  785.       data->name, disk_car->CHS.cylinder+1, disk_car->CHS.head+1, disk_car->CHS.sector,(disk_car->CHS.cylinder+1)*(disk_car->CHS.head+1)*disk_car->CHS.sector/2/1024);
  786.   return disk_car->description_txt;
  787. }
  788.  
  789. static int file_clean(t_param_disk *disk_car)
  790. {
  791.   if(disk_car->data!=NULL)
  792.   {
  793.     FREE(disk_car->data);
  794.     disk_car->data=NULL;
  795.   }
  796.   return 0;
  797. }
  798.  
  799. static int file_read(t_param_disk *disk_car,const unsigned int nbr_sector, void *nom_buffer, dword pos)
  800. {
  801.   struct info_file *data=disk_car->data;
  802.   long int ret;
  803. /* ecrit_rapport("file_read(%d,%u,buffer,%lu(%u/%u/%u))\n", data->handle,nbr_sector,pos, */
  804. /*     LBA2cylinder(disk_car,pos),LBA2head(disk_car,pos),LBA2sector(disk_car,pos)); */
  805. #ifdef TESTING
  806.   if(rand()%10==0)    /* TEST ONLY ICI */
  807.   {
  808. /*   ecrit_rapport("file_read(%u,%u,buffer,%lu) seek err\n", data->handle,nbr_sector,pos); */
  809.     return -1;
  810.   }
  811.   if(LBA2cylinder(disk_car,pos)>1 && LBA2cylinder(disk_car,pos)<600)
  812.   {
  813.     memset(nom_buffer,0,nbr_sector*SECTOR_SIZE);
  814.     return 0;
  815.   }
  816. #endif
  817.   if(lseek(data->handle,((loff_t)pos<<9)+(loff_t)data->offset,SEEK_SET)==-1)
  818.   {
  819.     ecrit_rapport("file_read(%d,%u,buffer,%lu(%u/%u/%u)) seek err %s\n", data->handle,nbr_sector,pos,
  820.       LBA2cylinder(disk_car,pos),LBA2head(disk_car,pos),LBA2sector(disk_car,pos),strerror(errno));
  821.     return -1;
  822.   }
  823.   ret=read(data->handle, nom_buffer, nbr_sector*SECTOR_SIZE);
  824.   if(ret!=(long int)(nbr_sector*SECTOR_SIZE))
  825.   {
  826.     ecrit_rapport("file_read(%d,%u,buffer,%lu(%u/%u/%u)) read err %s (ret!=nbr_sector*SECTOR_SIZE)\n", data->handle,nbr_sector,pos,
  827.       LBA2cylinder(disk_car,pos),LBA2head(disk_car,pos),LBA2sector(disk_car,pos),(ret==-1?strerror(errno):"Truncated file"));
  828.     return -1;
  829.   }
  830.   return 0;
  831. }
  832.  
  833. static int file_write(t_param_disk *disk_car,const unsigned int nbr_sector, const void *nom_buffer, const dword pos)
  834. {
  835.   long int ret;
  836.   struct info_file *data=disk_car->data;
  837.   if(lseek(data->handle,((loff_t)pos<<9)+(loff_t)(data->offset),SEEK_SET)==-1)
  838.   {
  839.     ecrit_rapport("file_write(%d,%u,buffer,%lu(%u/%u/%u)) seek err %s\n", data->handle,nbr_sector,pos,
  840.       LBA2cylinder(disk_car,pos),LBA2head(disk_car,pos),LBA2sector(disk_car,pos),strerror(errno));
  841.     return -1;
  842.   }
  843.   disk_car->write_used=1;
  844.   ret=write(data->handle, nom_buffer, nbr_sector*SECTOR_SIZE);
  845.   if(ret!=(long int)nbr_sector*SECTOR_SIZE)
  846.   {
  847.     ecrit_rapport("file_write(%d,%u,buffer,%lu(%u/%u/%u)) write err %s\n", data->handle,nbr_sector,pos,
  848.       LBA2cylinder(disk_car,pos),LBA2head(disk_car,pos),LBA2sector(disk_car,pos),(ret==-1?strerror(errno):"File truncated"));
  849.     return -1;
  850.   }
  851.   return 0;
  852. }
  853.  
  854. static int file_nowrite(t_param_disk *disk_car,const unsigned int nbr_sector, const void *nom_buffer, const dword pos)
  855. {
  856.   struct info_file *data=disk_car->data;
  857.   ecrit_rapport("write_file(%d,%u,buffer,%lu(%u/%u/%u)) write refused\n", data->handle,nbr_sector,pos,
  858.       LBA2cylinder(disk_car,pos),LBA2head(disk_car,pos),LBA2sector(disk_car,pos));
  859.   return -1;
  860. }
  861.  
  862. t_param_disk *file_test_availability(const char *device, const int debug)
  863. {
  864.   unsigned int offset=0;
  865.   t_param_disk *disk_car=NULL;
  866.   int hd_h;
  867.   int no_write=0;
  868. #ifdef O_LARGEFILE
  869.   hd_h = open(device, O_RDWR|O_LARGEFILE|O_BINARY);
  870. #else
  871.   hd_h = open(device, O_RDWR|O_BINARY);
  872. #endif
  873.   if(hd_h<0)
  874.   {
  875.     if(debug>1)
  876.     {
  877.       ecrit_rapport("file_test_availability %s:%s\n", device,strerror(errno));
  878.     }
  879. /*   if(errno==EROFS||errno==EACCES|errno==EPERM) */
  880.     {
  881.       no_write=1;
  882. #ifdef O_LARGEFILE
  883.       hd_h = open(device, O_RDONLY|O_LARGEFILE|O_BINARY);
  884. #else
  885.       hd_h = open(device, O_RDONLY|O_BINARY);
  886. #endif
  887.       if(hd_h<0)
  888.       {
  889.     if(debug>1)
  890.     {
  891.       ecrit_rapport("file_test_availability %s:%s\n", device,strerror(errno));
  892.     }
  893.       }
  894.     }
  895.   }
  896.   if(hd_h>0)
  897.   {
  898.     struct stat stat_rec;
  899.     if(fstat(hd_h,&stat_rec)<0)
  900.     {
  901.       if(debug>1)
  902.       {
  903.     ecrit_rapport("file_test_availability %s: fstat failed\n",device);
  904.       }
  905.       close(hd_h);
  906.       return NULL;
  907.     }
  908.     if(!S_ISREG(stat_rec.st_mode))
  909.     {
  910.       if(debug>1)
  911.       {
  912.     ecrit_rapport("file_test_availability %s: not a regular file\n",device);
  913.       }
  914. #ifndef DJGPP
  915.       disk_car=disk_get_geometry(hd_h, device, debug);
  916.       if(disk_car!=NULL)
  917.       {
  918.     disk_car->size=(disk_car->CHS.cylinder+1)*(disk_car->CHS.head+1)*disk_car->CHS.sector;
  919.       }
  920. #endif
  921.     }
  922.     else
  923.     {
  924.       unsigned char buffer[SECTOR_SIZE];
  925.       if(read(hd_h,buffer,sizeof(buffer))!=sizeof(buffer))
  926.       {
  927.     close(hd_h);
  928.     return NULL;
  929.       }
  930.       if(memcmp(buffer,"DOSEMU",6)==0)
  931.       {
  932.     if(*(unsigned long*)(buffer+11)==0)
  933.     {
  934.       ecrit_rapport("%s corrupted DOSEMU file\n",device);
  935.       close(hd_h);
  936.       return NULL;
  937.     }
  938.     if(debug)
  939.     {
  940.       ecrit_rapport("%s DOSEMU\n",device);
  941.     }
  942.     disk_car=(t_param_disk *)MALLOC(sizeof(*disk_car));
  943.     disk_car->CHS.head=*(unsigned long*)(buffer+7)-1;
  944.     disk_car->CHS.sector=*(unsigned long*)(buffer+11);
  945.     disk_car->CHS.cylinder=*(unsigned long*)(buffer+15)-1;
  946.     disk_car->size=(disk_car->CHS.cylinder+1)*(disk_car->CHS.head+1)*disk_car->CHS.sector;
  947.     offset=*(unsigned long*)(buffer+19);
  948.       }
  949.       else
  950.       {
  951.     t_CHS geometry;
  952.     disk_car=(t_param_disk *)MALLOC(sizeof(*disk_car));
  953.     disk_car->size=(stat_rec.st_size-offset)/SECTOR_SIZE;
  954.     get_geometry_from_mbr(buffer, debug, &geometry);
  955.     if(geometry.sector>0)
  956.     {
  957.       disk_car->CHS.head=geometry.head;
  958.       disk_car->CHS.sector=geometry.sector;
  959.     }
  960.     else
  961.     {
  962.       disk_car->CHS.head=255-1;
  963.       disk_car->CHS.sector=63;
  964.     }
  965.     /* Round up because file is often truncated. */
  966.     disk_car->CHS.cylinder=(disk_car->size+disk_car->CHS.sector*(disk_car->CHS.head+1)-1)/disk_car->CHS.sector/(disk_car->CHS.head+1)-1;
  967.       }
  968.     }
  969.     if(disk_car!=NULL)
  970.     {
  971.       struct info_file *data=MALLOC(sizeof(*data));
  972.       data->offset=offset;
  973.       strncpy(data->name,device,sizeof(data->name));
  974.       data->handle=hd_h;
  975.       disk_car->halt_on_errors=0;
  976.       disk_car->write_used=0;
  977.       disk_car->description=file_description;
  978.       disk_car->read=file_read;
  979.       disk_car->write=(no_write==0?file_write:file_nowrite);
  980.       disk_car->clean=file_clean;
  981.       disk_car->data=data;
  982.       return disk_car;
  983.     }
  984.     else
  985.     {
  986.       close(hd_h);
  987.     }
  988.   }
  989.   return NULL;
  990. }
  991.  
  992. void hd_parse_bis(const t_list_disk * list_disk, const int allow_partial_last_cylinder)
  993. {
  994.   const t_list_disk *element_disk;
  995.   for(element_disk=list_disk;element_disk;element_disk=element_disk->next)
  996.   {
  997.     t_param_disk *disk_car=element_disk->disk;
  998.     char buffer[SECTOR_SIZE];
  999.     dword pos;
  1000.     t_CHS pos_CHS;
  1001.     dup_t_CHS(&pos_CHS,&disk_car->CHS);
  1002.     pos_CHS.cylinder++;
  1003.     if(allow_partial_last_cylinder) {
  1004.       pos_CHS.head=0;
  1005.       pos_CHS.sector=1;
  1006.     }
  1007.     pos=CHS2LBA(disk_car,&pos_CHS);
  1008. #ifdef DJGPP
  1009.     if(disk_car->description==disk_description)
  1010.     {
  1011.       struct info_disk*data=disk_car->data;
  1012.       data->CHSR.cylinder=0;
  1013.     }
  1014. #endif
  1015.     if(disk_car->read(element_disk->disk,1, &buffer, pos)==0)
  1016.     {
  1017.       disk_car->CHS.cylinder++;
  1018.       if(disk_car->size < (disk_car->CHS.cylinder+1)*(disk_car->CHS.head+1)*disk_car->CHS.sector)
  1019.       {
  1020.     disk_car->size=(disk_car->CHS.cylinder+1)*(disk_car->CHS.head+1)*disk_car->CHS.sector;
  1021.     ecrit_rapport("Computes LBA from CHS for %s\n",disk_car->description(disk_car));
  1022.       }
  1023.     }
  1024. #ifdef DJGPP
  1025.     if(disk_car->description==disk_description)
  1026.     {
  1027.       struct info_disk*data=disk_car->data;
  1028.       data->CHSR.cylinder=disk_car->CHS.cylinder;
  1029.     }
  1030. #endif
  1031.   }
  1032. }
  1033.  
  1034. #ifdef TEST
  1035. struct info_cache
  1036. {
  1037.   t_param_disk *disk_car;
  1038.   unsigned int nbr_read;
  1039.   unsigned int nbr_write;
  1040. };
  1041.  
  1042. static int cache_read(t_param_disk *disk_car,const unsigned int nbr_sector, void *nom_buffer, const dword pos);
  1043. static int cache_write(t_param_disk *disk_car,const unsigned int nbr_sector, const void *nom_buffer, const dword pos);
  1044. static int cache_clean(t_param_disk *clean);
  1045.  
  1046. static int cache_read(t_param_disk *disk_car,const unsigned int nbr_sector, void *nom_buffer, const dword pos)
  1047. {
  1048.   static char buffer[8*SECTOR_SIZE];
  1049.   static dword old_pos=1234;
  1050.   int res=0;
  1051.   struct info_cache *data=disk_car->data;
  1052.   ecrit_rapport("cache_read(%u,buffer,%lu(%u/%u/%u))\n", nbr_sector,pos,
  1053.       LBA2cylinder(disk_car,pos),LBA2head(disk_car,pos),LBA2sector(disk_car,pos));
  1054.   if(nbr_sector>8)
  1055.   {
  1056.     data->nbr_read+=nbr_sector;
  1057.     return data->disk_car->read(data->disk_car,nbr_sector,nom_buffer,pos);
  1058.   }
  1059.   if(pos!=old_pos)
  1060.   {
  1061.     res=data->disk_car->read(data->disk_car,8,buffer,pos);
  1062.     data->nbr_read+=8;
  1063.   } else {
  1064.     ecrit_rapport("Cached\n");
  1065.   }
  1066.   memcpy(nom_buffer,buffer,nbr_sector*SECTOR_SIZE);
  1067.   return res;
  1068. }
  1069.  
  1070. static int cache_write(t_param_disk *disk_car,const unsigned int nbr_sector, const void *nom_buffer, const dword pos)
  1071. {
  1072.   struct info_cache *data=disk_car->data;
  1073.   data->nbr_write+=nbr_sector;
  1074.   disk_car->write_used=1;
  1075.   return data->disk_car->write(data->disk_car,nbr_sector,nom_buffer,pos);
  1076. }
  1077.  
  1078. static int cache_clean(t_param_disk *disk_car)
  1079. {
  1080.   if(disk_car->data)
  1081.   {
  1082.     struct info_cache *data=disk_car->data;
  1083.     ecrit_rapport("nbr_read  %u, nbr_write %u\n",data->nbr_read,data->nbr_write);
  1084.     data->disk_car->clean(data->disk_car);
  1085.     FREE(data->disk_car);
  1086.     FREE(disk_car->data);
  1087.     disk_car->data=NULL;
  1088.   }
  1089.   return 0;
  1090. }
  1091.  
  1092. static t_param_disk *new_diskcache(t_param_disk *disk_car)
  1093. {
  1094.   struct info_cache*data=MALLOC(sizeof(*data));
  1095.   t_param_disk *new_disk_car=MALLOC(sizeof(*new_disk_car));
  1096.   memcpy(new_disk_car,disk_car,sizeof(*new_disk_car));
  1097.   data->disk_car=disk_car;
  1098.   data->nbr_read=0;
  1099.   data->nbr_write=0;
  1100.   new_disk_car->halt_on_errors=0;
  1101.   new_disk_car->write_used=0;
  1102.   new_disk_car->data=data;
  1103.   new_disk_car->description=disk_car->description;
  1104.   new_disk_car->read=cache_read;
  1105.   new_disk_car->write=cache_write;
  1106.   new_disk_car->clean=cache_clean;
  1107.   return new_disk_car;
  1108. }
  1109. #endif
  1110.